const { WebSocketServer } = require('ws');

// 1. 初始化服务
const wss = new WebSocketServer({ port: 8099 });

// 2. 设备连接存储
const devices = new Map(); // deviceId -> WebSocket

const messageLog = new Map(); // 存储消息追踪记录

// 3. 心跳检测配置
const HEARTBEAT_INTERVAL = 30000; // 30秒

// 4. 连接处理
wss.on('connection', (ws, req) => {
  // 4.1 提取设备ID (如 ws://localhost:8080?deviceId=DEV001)
  const params = new URLSearchParams(req.url.split('?')[1] || '');
  const deviceId = params.get('deviceId');

  if (!deviceId) {
    ws.close(1008, 'Missing deviceId');
    return;
  }

  console.log(`[连接] 设备 ${deviceId} 上线`);

  // 4.2 踢掉旧连接
  if (devices.has(deviceId)) {
    devices.get(deviceId).close(1001, '重复连接');
  }
  devices.set(deviceId, ws);
  ws.deviceId = deviceId;

  // 4.3 心跳设置
  ws.isAlive = true;
  ws.on('pong', () => ws.isAlive = true);

  // 4.4 消息处理
  ws.on('message', (data) => {
    try {
      const msg = parseMessage(data);
      // --- 消息路由开始 ---
	  if(msg.type === 'heartbeat'){
		  //心跳检测
		  console.log("heartbeat：" + msg.deviceId)
	  }else if (msg.type === 'broadcast') {
        // 1. 广播消息（发给所有人，除了自己）
        broadcast(ws, msg);
      } else if(msg.type === 'unicast') {
        // 2. 单播消息（发给指定设备）
        unicast(ws, msg);
      }else{
		  console.log(msg);
	  }
      // --- 消息路由结束 ---
    } catch (err) {
      handleError(ws, err);
    }
  });

  // 4.5 连接清理
  ws.on('close', () => {
    if (devices.get(deviceId) === ws) {
      devices.delete(deviceId);
      console.log(`[断开] 设备 ${deviceId} 下线`);
    }
  });
});

// 5. 心跳检测
setInterval(() => {
  devices.forEach((ws, deviceId) => {
    if (!ws.isAlive) {
      console.log(`设备${deviceId}心跳超时，强制断开`);
       ws.terminate();
	   devices.delete(deviceId);
	   return;
    }
    ws.isAlive = false;
    ws.ping();
  });
  console.log(`当前连接设备数: ${devices.size}`);
}, HEARTBEAT_INTERVAL);

// --------------------------
// 核心消息处理函数
// --------------------------

/**
 * 1. 广播消息（发给所有设备，除了发送者）
 */
function broadcast(senderWs, msg) {
  devices.forEach((ws, deviceId) => {
    if (ws !== senderWs && ws.readyState === ws.OPEN) {
      ws.send(JSON.stringify({
        ...msg,
        from: senderWs.deviceId,
        timestamp: Date.now()
      }));
    }
  });
  console.log(`[广播] ${senderWs.deviceId} -> 所有设备`);
}

/**
 * 2. 单播消息（发给指定设备）
 */
function unicast(senderWs, msg) {
 // 检查 targetDeviceId 是否存在
   if (!msg.targetDeviceId) {
     const errorAck = {
       type: 'ack',
       msgId: msg.msgId || 'unknown', // 防止 msg 未定义
       status: 'error',
       message: '单播消息需要 targetDeviceId',
       timestamp: Date.now()
     };
     
     // 发送错误回执给发送端
     senderWs.send(JSON.stringify(errorAck));
     console.log(`[错误] 设备 ${senderWs.deviceId} 发送的消息缺少 targetDeviceId`);
     return; 
   }
 
   // 目标设备检查
   const targetWs = devices.get(msg.targetDeviceId);
   if (!targetWs) {
     senderWs.send(JSON.stringify({
       type: 'ack',
       msgId: msg.msgId,
       status: 'error',
       message: `目标设备 ${msg.targetDeviceId} 离线`,
       timestamp: Date.now()
     }));
	 console.log(`[错误] 目标设备 ${msg.targetDeviceId} 离线`);
     return;
   }
   // 消息追踪
     // const delivery = {
     //   sender: senderWs.deviceId,
     //   target: msg.targetDeviceId,
     //   msgId: msg.msgId,
     //   timestamp: Date.now(),
     //   status: 'pending'
     // };
     // messageLog.set(msg.msgId, delivery);
	 
   // 发送投递回执
   senderWs.send(JSON.stringify({
     type: 'ack',
     msgId: msg.msgId,
     status: 'delivered',
	 message: `目标设备 ${msg.targetDeviceId} 已收到`,
     timestamp: Date.now()
   }));
	// 转发消息
  targetWs.send(JSON.stringify({
	...msg,
	from: senderWs.deviceId,
	timestamp: Date.now()
  }));
    console.log(`[单播] ${senderWs.deviceId} -> ${msg.targetDeviceId}`);
}

// --------------------------
// 工具函数
// --------------------------

function parseMessage(data) {
  try {
	  // 统一转换为字符串
	const rawData = data.toString('utf-8');
    const msg = JSON.parse(data);
    if (!msg.type) throw new Error('消息缺少 type 字段');
    return msg;
  } catch (e) {
    throw new Error('消息必须是JSON格式');
  }
}

function handleError(ws, err) {
  console.error(`[错误] ${ws.deviceId}:`, err.message);
  ws.send(JSON.stringify({
    status: 'error',
    error: err.message
  }));
}

console.log('WebSocket 服务已启动: ws://8.140.55.249:8099');